package icraf.carbon.gui;

import icraf.carbon.core.LandCover;
import icraf.carbon.core.LandCoverList;
import icraf.carbon.core.Project;
import icraf.carbon.core.Zone;
import icraf.carbon.gui.MenuFactory.MenuProperty;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableModel;

public class LCListPanel extends JPanel implements ActionListener {

	class LCListModel extends MatrixTableModel {
		private static final long serialVersionUID = 8968868974903218229L;
		private String[] headers = { MenuProperty.PROJECT_LANDUSE.getLabel(), MenuProperty.INPUT_DESC.getLabel() };
		private NumberRowHeader tableListModel = new NumberRowHeader(this);

		public void addNew() {
			if (project == null)
				return;
			int n = project.getLandCoverList().size();
			project.getLandCoverList()
					.add(new LandCover(MenuProperty.PROJECT_LANDUSE.getLabel() + " " + (n + 1)));
			this.fireTableRowsInserted(n, n);
		}

		public void delete(int[] idx) {
			if (project == null)
				return;
			ArrayList<LandCover> ls = new ArrayList<LandCover>();
			for (int i : idx) {
				ls.add(project.getLandCoverList().get(i));
			}
			project.getLandCoverList().removeAll(ls);
			for (int i = 0; i < project.getZoneList().getSize(); i++) {
				Zone z = project.getZoneList().get(i);
				for (LandCover lc : ls) {
					z.removeLandCover(lc);
				}
			}
			this.fireTableDataChanged();
		}

		@Override
		public void fireTableDataChanged() {
			super.fireTableDataChanged();
			tableListModel.fireContentChange(this.getRowCount());
		}

		@Override
		public void fireTableRowsInserted(int firstRow, int lastRow) {
			super.fireTableRowsInserted(firstRow, lastRow);
			tableListModel.fireContentChange(this.getRowCount());
		}

		@Override
		public Class<?> getColumnClass(int column) {
			return String.class;
		}

		@Override
		public int getColumnCount() {
			return headers.length;
		}

		@Override
		public String getColumnName(int col) {
			return headers[col];
		}

		@Override
		public int getRowCount() {
			if (project == null)
				return 0;
			return project.getLandCoverList().size();
		}

		@Override
		public ListModel<Object> getRowHeaderModel() {
			return tableListModel;
		}

		@Override
		public Object getValueAt(int row, int column) {
			LandCover lc = project.getLandCoverList().get(row);
			switch (column) {
			case 0:
				return lc.getLabel();
			case 1:
				return lc.getDescription();
			}
			return null;
		}

		@Override
		public boolean isCellEditable(int row, int col) {
			return true;
		}

		@Override
		public void setValueAt(Object value, int row, int col) {
			if (value == null)
				return;
			LandCover lc = project.getLandCoverList().get(row);
			if (col == 0) {
				lc.setLabel(value.toString());
			} else if (col == 1) {
				lc.setDescription(value.toString());
			}
			fireTableCellUpdated(row, col);
		}

		public void importFromClipboard(ClipboardPanel clipboardPanel) {
			TableModel table = clipboardPanel.getTableModel();
			if (table.getRowCount() <= 0)
				return;
			LandCoverList list = project.getLandCoverList();
			int i = 0;

			for (LandCover lc : list) {
				if (table.getRowCount() < i + 1)
					break;
				lc.setLabel(table.getValueAt(i, 0).toString());
				if (table.getColumnCount() == 2)
					lc.setDescription(table.getValueAt(i, 1).toString());
				i++;
			}

			for (int j = i; j < table.getRowCount(); j++) {
				LandCover lc = new LandCover(table.getValueAt(j, 0).toString());
				list.add(lc);
				if (table.getColumnCount() == 2)
					lc.setDescription(table.getValueAt(j, 1).toString());
			}
			fireTableDataChanged();
		}

	}

	private static final long serialVersionUID = -1812214166165551697L;

	public static void main(String[] args) {
		final JFrame frame = new JFrame();
		frame.setSize(new Dimension(300, 300));
		LCListPanel p = new LCListPanel();
		p.setProject(new Project(3));
		// p.setLandCoverList(new LandCoverList());
		frame.getContentPane().add(p, BorderLayout.CENTER);
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}

		});
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				frame.setVisible(true);
			}
		});

	}

	private LCListModel lcListModel = new LCListModel();
	private ListToolBar listToolBar;
	private MatrixPanel matrixPanel;
	private Project project;
	private ClipboardPanel clipboardPanel = new ClipboardPanel();
	private JPanel importClipboardPanel;

	public LCListPanel() {
		setLayout(new BorderLayout());
		JPanel mainPanel = new JPanel(new BorderLayout());
		matrixPanel = new MatrixPanel(lcListModel);
		matrixPanel.getTable().setAutoResizeMode(
				JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
		mainPanel.add(matrixPanel);

		listToolBar = new ListToolBar(this);
		listToolBar.setFloatable(false);

		listToolBar.addSeparator();
		listToolBar.add(MenuFactory.createButtonIcon(
				MenuProperty.LIST_IMPORT_CLIPBOARD, this));
		mainPanel.add(listToolBar, BorderLayout.NORTH);

		this.add(mainPanel);

		// TODO: mungkin conflict -> double definition!
		matrixPanel.getTable().getInputMap()
				.put(KeyStroke.getKeyStroke("DELETE"), "delete");
		matrixPanel.getTable().getActionMap()
				.put("delete", new AbstractAction() {
					private static final long serialVersionUID = -3884027154884332834L;

					@Override
					public void actionPerformed(ActionEvent e) {
						remove();
					}
				});

		String[] h = new String[lcListModel.getColumnCount()];
		for (int i = 0; i < h.length; i++) {
			h[i] = lcListModel.getColumnName(i);
		}
		clipboardPanel.setFields(h);
		clipboardPanel.setPreferredSize(new Dimension(300, 300));
		importClipboardPanel = new JPanel();
		importClipboardPanel.setLayout(new BorderLayout(5, 5));
		importClipboardPanel.add(new JLabel(MenuProperty.LIST_IMPORT_CLIPBOARD.getAccessibleDescription() ),
				BorderLayout.NORTH);
		importClipboardPanel.add(clipboardPanel);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (MenuProperty.LIST_ADD.isAction(e)) {
			lcListModel.addNew();
			project.getLandCoverList().setUpdated(true);
		} else if (MenuProperty.LIST_REMOVE.isAction(e)) {
			remove();
		} else if (MenuProperty.LIST_IMPORT_CLIPBOARD.isAction(e)) {
			clipboardPanel.updateClipboardData();
			int opt = JOptionPane.showConfirmDialog(this, importClipboardPanel,
					MenuProperty.LIST_IMPORT_CLIPBOARD.getLabel(), JOptionPane.YES_NO_OPTION,
					JOptionPane.PLAIN_MESSAGE);
			if (opt == JOptionPane.YES_OPTION) {
				lcListModel.importFromClipboard(clipboardPanel);
			}
		}
	}

	public ListToolBar getListToolBar() {
		return listToolBar;
	}

	private void remove() {
		int sel[] = matrixPanel.getTable().getSelectedRows();
		if (sel.length <= 0)
			return;
		if (project.getLandCoverList().size() == 1) {
			JOptionPane
					.showMessageDialog(
							this,
							MenuProperty.PROJECT_REMOVE_LU_ERROR.getAccessibleDescription(),
							MenuProperty.PROJECT_REMOVE_LU_ERROR.getLabel(),
							JOptionPane.INFORMATION_MESSAGE);
			return;
		}

		int opt = JOptionPane
				.showConfirmDialog(
						this,
						MenuProperty.PROJECT_REMOVE_LU.getAccessibleDescription(),
						MenuProperty.PROJECT_REMOVE_LU.getLabel(),
						JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
		if (opt != JOptionPane.YES_OPTION)
			return;
		lcListModel.delete(sel);
		project.getLandCoverList().setUpdated(true);
	}

	public void setProject(Project project) {
		this.project = project;
		lcListModel.fireTableDataChanged();
	}
}
